using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using Microsoft.WowAddonStudio.FrameXml.Components.Events.ScriptManager;

namespace Microsoft.WowAddonStudio.FrameXml.Components.Events.Editors
{
    [ToolboxItem(false)]
    public partial class EventEditorUserControl : UserControl
    {
        private static readonly Regex regex = new Regex(@"(?i)^\s*([A-Za-z_][A-Za-z0-9_]*)?\s*(\(\s*\))?\s*(;)?\s*$");
        private string script;

        /// <summary>
        /// Initializes a new instance of the <see cref="EventEditorUserControl"/> class.
        /// </summary>
        /// <param name="frame">The frame.</param>
        /// <param name="eventName">Name of the event.</param>
        /// <param name="editorService">The ed SVC.</param>
        /// <param name="scriptManager">The script manager.</param>
        public EventEditorUserControl(IFrameXmlControl frame, string eventName, IWindowsFormsEditorService editorService, IFrameXmlScriptManager scriptManager)
            : this()
        {
            FrameXmlControl = frame;
            EventName = eventName;
            EditorService = editorService;
            ScriptManager = scriptManager;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EventEditorUserControl"/> class.
        /// </summary>
        private EventEditorUserControl()
        {
            InitializeComponent();

            buttonCreateJump.Image = Resources.VSObject_Event;
            buttonCreateJump.ImageTransparentColor = Color.Magenta;
            buttonEdit.Image = Resources.EditInformation;
            buttonEdit.ImageTransparentColor = buttonCreateJump.ImageTransparentColor;
            buttonDelete.Image = Resources.Delete;
            buttonDelete.ImageTransparentColor = buttonCreateJump.ImageTransparentColor;

            if (commandStrip.Items.Count == 0)
                commandStrip.Items.AddRange(new ToolStripItem[]
                                                {
                                                    buttonCreateJump,
                                                    buttonEdit, toolStripSeparator, buttonDelete
                                                });
        }

        /// <summary>
        /// Gets or sets the editor service.
        /// </summary>
        /// <value>The editor service.</value>
        protected IWindowsFormsEditorService EditorService { get; private set; }

        /// <summary>
        /// Gets or sets the script manager.
        /// </summary>
        /// <value>The script manager.</value>
        protected IFrameXmlScriptManager ScriptManager { get; private set; }

        /// <summary>
        /// Gets or sets the frame XML control.
        /// </summary>
        /// <value>The frame XML control.</value>
        private IFrameXmlControl FrameXmlControl { get; set; }

        /// <summary>
        /// Gets or sets the name of the event.
        /// </summary>
        /// <value>The name of the event.</value>
        private string EventName { get; set; }

        /// <summary>
        /// Gets or sets the script.
        /// </summary>
        /// <value>The script.</value>
        public string Script
        {
            get { return textBoxScript.Text; }
            set
            {
                script = value;
                textBoxScript.Text = script;
                SetButtonProperties();
            }
        }

        /// <summary>
        /// Handles the Click event of the buttonEditScript control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void buttonEditScript_Click(object sender, EventArgs e)
        {
            using (var form = new EventEditorForm())
            {
                form.Script = Script;
                if (form.ShowDialog() == DialogResult.OK)
                {
                    Script = form.Script;
                }
            }
        }

        /// <summary>
        /// Handles the Click event of the buttonCreateJump control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void buttonCreateJump_Click(object sender, EventArgs e)
        {
            string eventHandlerName;

            if (Script.Trim().Length == 0)
            {
                eventHandlerName = String.Format(CultureInfo.InvariantCulture, "{0}_{1}", FrameXmlControl.Name, EventName);
            }
            else
            {
                Match match = regex.Match(Script);
                if (!match.Groups[1].Success)
                    return;

                eventHandlerName = match.Groups[1].Value;
            }

            // adds the code to the textbox
            Script = eventHandlerName + "();";
            EditorService.CloseDropDown();

            // ugly, but required :)
            // opening of the LUA editor dismisses the event property editing.
            // DoEvents assures that property editing is finished while the lua script editing commences on a new thread.
            Application.DoEvents();

            ThreadPool.QueueUserWorkItem(EditScript, Script);
            //EditScript(eventHandlerName);
        }

        /// <summary>
        /// Edits the script.
        /// </summary>
        /// <param name="eventHandlerNameObject">The event handler name object.</param>
        private void EditScript(object eventHandlerNameObject)
        {
            try
            {
                var eventHandlerName = (string) eventHandlerNameObject;
                if (!string.IsNullOrEmpty(eventHandlerName))
                    ScriptManager.CreateOrShowFunction(eventHandlerName);
            }
            catch (Exception e)
            {
                Trace.WriteLine(e);
            }
        }

        /// <summary>
        /// Handles the TextChanged event of the textBoxScript control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void textBoxScript_TextChanged(object sender, EventArgs e)
        {
            SetButtonProperties();
        }


        /// <summary>
        /// Sets the button properties.
        /// </summary>
        private void SetButtonProperties()
        {
            Match match = regex.Match(Script);

            buttonCreateJump.Enabled = ScriptManager.IsValid && match.Success;
            if (buttonCreateJump.Enabled)
            {
                buttonCreateJump.Text = match.Groups[1].Success
                                            ?
                                                "Jump"
                                            :
                                                "Create";
            }
            else
            {
                buttonCreateJump.Text = ScriptManager.IsValid
                                            ?
                                                "Wrong name"
                                            :
                                                "No script file";
            }

            string toolTipText = !ScriptManager.IsValid
                                     ?
                                         "There is no .lua file associated with this frame xml."
                                     :
                                         !match.Success ? "This is not an event handler name." : "";

            buttonCreateJump.ToolTipText = toolTipText;
        }

        /// <summary>
        /// Handles the Click event of the buttonDelete control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void buttonDelete_Click(object sender, EventArgs e)
        {
            textBoxScript.Clear();
        }
    }
}